package 多线程.Unsafe;

import sun.misc.Unsafe;

/**
 * Unsafe类提供了硬件级别的的原子性操作，Unsafe类中的方法都是native方法，通过使用JNI的方式访问本地C++库
 *
 * long objectFieldOffset(Field field） 方法: 返回指定的变量在所属类中的内存偏移地址
 * int arrayBaseOffset(Class arrayClass） 方法： 获取数组中第一个元素的地址
 * boolean compareAndSwapLong(Object obj, long offset, long expect, long update） 方法: CAS操作
 * public native long getLongvolatile(Object obj, long offset） 方法： 获取对象obj中偏移量offset 的变量对应volatile语义的值
 * void putLongvolatile(Object obj, long offset, long value）方 法： 设置 obj 对 象 中 offset
 * 偏移 的类型为 long 的 field 的值为 value ，支持 volatile 语义
 * void park(boolean isAbsolute, long time） 方法： 阻塞当前线程
 * void unpark(Object thread） 方法： 唤醒调用park后阻塞的线程
 * long getAndSetLong(Object obj , long offset, long update） 方法： 获取对象 obj 中偏移
 * 量为offset 的变量 volatile语义的当前值 ，并设置变量 volatile 语义的值为 update
 * long getAndAddLong(Object obj, long offset, long addValue） 方法： 获取对象obj中偏移
 * 量为 offset 的变量 volatile 语义的当前值 ，并设置变量值为原始值＋addValue

 */
public class UnsafeDemo1 {
    volatile long state = 0;//变量
    static final Unsafe UNSAFE = Unsafe.getUnsafe();//获取Unsafe的实例
    static long stateOffset;//记录变量state在类UnSafeDemo类中的偏移值
    static {
        try {
            //获取state变量在类UnSafeDemo中的偏移值
            stateOffset = UNSAFE.objectFieldOffset(UnsafeDemo1.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        UnsafeDemo1 uDemo=new UnsafeDemo1();
        //将state的值更新为1
        Boolean success=UNSAFE.compareAndSwapInt(uDemo, stateOffset,0,1);
        System.out.println(success);
    }
}

/**
 * private Unsafe() {}
 *
 * private static final Unsafe theUnsafe = new Unsafe();
 *
 * @CallerSensitive
 * public static Unsafe getUnsafe() {
 * //获取调用 getUnsafe 这个方法的对 象 的 Class 对象
 *    Class<?> caller = Reflection.getCallerClass();
 * //判断是不是 Bootstrap 类 加载器加载的localClass
 *    if (!VM.isSystemDomainLoader(caller.getClassLoader()))
 *        throw new SecurityException("Unsafe");
 *    return theUnsafe;
 *
 * }
 *
 * 从代码中可以看出原因如下：
 * UnsafeDemo是AppClassLoader应用程序加载器加载的，不是启动类加载器加载的，因此报错，这是一种安全机制，
 * 如果没有这种机制，应用程序就可以直接使用Unsafe类操作内存。
 *
 * 但是我们可以使用反射来使用UnSafe类：
 */
